﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using University.Workshop.Model.CardGame;
using System.Collections.ObjectModel;

namespace University.Workshop.Model.CardGame
{
    public enum PokerScore
    {
        None, JacksOrBetter, TwoPair, ThreeOfAKind,
        Straight, Flush, FullHouse, FourOfAKind, StraightFlush,
        RoyalFlush
    }

    public sealed class Statistics
    {
        private Statistics()
        {
        }

        private static bool IsFlush(Collection<Card> myHand)
        {
            if (myHand[0].SuitProperties == myHand[1].SuitProperties &&
                myHand[1].SuitProperties == myHand[2].SuitProperties &&
                myHand[2].SuitProperties == myHand[3].SuitProperties &&
                myHand[3].SuitProperties == myHand[4].SuitProperties)
            {
                return (true);
            }
            return (false);
        }


        private static bool IsStraight(Collection<Card> myHand)
        {
            if (myHand[0].RankProperties == myHand[1].RankProperties - 1 &&
                myHand[1].RankProperties == myHand[2].RankProperties - 1 &&
                myHand[2].RankProperties == myHand[3].RankProperties - 1 &&
                myHand[3].RankProperties == myHand[4].RankProperties - 1)
            {
                return (true);
            }

            if (myHand[1].RankProperties == EnumRank.Ten &&
                myHand[2].RankProperties == EnumRank.Jack &&
                myHand[3].RankProperties == EnumRank.Queen &&
                myHand[4].RankProperties == EnumRank.King &&
                myHand[0].RankProperties == EnumRank.Ace)
            {
                return (true);
            }
            return (false);
        }

        private static bool IsRoyalFlush(Collection<Card> myHand)
        {
            if (IsStraight(myHand) && IsFlush(myHand) &&
                  myHand[0].RankProperties == EnumRank.Ace &&
                  myHand[1].RankProperties == EnumRank.Ten &&
                  myHand[2].RankProperties == EnumRank.Jack &&
                  myHand[3].RankProperties == EnumRank.Queen &&
                  myHand[4].RankProperties == EnumRank.King)
            {
                return (true);
            }
            return (false);
        }

        private static bool IsStraightFlush(Collection<Card> myHand)
        {
            if (IsStraight(myHand) && IsFlush(myHand))
            {
                return (true);
            }
            return (false);
        }

        private static bool IsFourOfAKind(Collection<Card> myHand)
        {
            if (myHand[0].RankProperties == myHand[1].RankProperties &&
                myHand[1].RankProperties == myHand[2].RankProperties &&
                myHand[2].RankProperties == myHand[3].RankProperties)
            {
                return (true);
            }

            if (myHand[1].RankProperties == myHand[2].RankProperties &&
                myHand[2].RankProperties == myHand[3].RankProperties &&
                myHand[3].RankProperties == myHand[4].RankProperties)
            {
                return (true);
            }
            return (false);
        }

        private static bool IsFullHouse(Collection<Card> myHand)
        {
            if (myHand[0].RankProperties == myHand[1].RankProperties &&
                myHand[2].RankProperties == myHand[3].RankProperties &&
                myHand[3].RankProperties == myHand[4].RankProperties)
            {
                return (true);
            }

            if (myHand[0].RankProperties == myHand[1].RankProperties &&
                myHand[1].RankProperties == myHand[2].RankProperties &&
                myHand[3].RankProperties == myHand[4].RankProperties)
            {
                return (true);
            }
            return (false);
        }

        private static bool IsThreeOfAKind(Collection<Card> myHand)
        {
            if (myHand[0].RankProperties == myHand[1].RankProperties &&
                myHand[1].RankProperties == myHand[2].RankProperties)
            {
                return (true);
            }

            if (myHand[1].RankProperties == myHand[2].RankProperties &&
                myHand[2].RankProperties == myHand[3].RankProperties)
            {
                return (true);
            }

            if (myHand[2].RankProperties == myHand[3].RankProperties &&
                myHand[3].RankProperties == myHand[4].RankProperties)
            {
                return (true);
            }

            return (false);
        }
        private static bool IsTwoPair(Collection<Card> myHand)
        {
            if (myHand[0].RankProperties == myHand[1].RankProperties &&
                myHand[2].RankProperties == myHand[3].RankProperties)
            {
                return (true);
            }

            if (myHand[0].RankProperties == myHand[1].RankProperties &&
                myHand[3].RankProperties == myHand[4].RankProperties)
            {
                return (true);
            }

            if (myHand[1].RankProperties == myHand[2].RankProperties &&
                myHand[3].RankProperties == myHand[4].RankProperties)
            {
                return (true);
            }

            return (false);
        }


        private static bool IsJacksOrBetter(Collection<Card> myHand)
        {
            if (myHand[0].RankProperties == myHand[1].RankProperties &&
                myHand[0].IsJacksOrBetter())
            {
                return (true);
            }

            if (myHand[1].RankProperties == myHand[2].RankProperties &&
                myHand[1].IsJacksOrBetter())
            {
                return (true);
            }

            if (myHand[2].RankProperties == myHand[3].RankProperties &&
                myHand[2].IsJacksOrBetter())
            {
                return (true);
            }

            if (myHand[3].RankProperties == myHand[4].RankProperties &&
                myHand[3].IsJacksOrBetter())
            {
                return (true);
            }

            return (false);
        }


        private static PokerScore ScoreCalculator(Collection<Card> myHand)
        {
            if (IsRoyalFlush(myHand))
                return PokerScore.RoyalFlush;
            else if (IsStraightFlush(myHand))
                return PokerScore.StraightFlush;
            else if (IsFourOfAKind(myHand))
                return PokerScore.FourOfAKind;
            else if (IsFullHouse(myHand))
                return PokerScore.FullHouse;
            else if (IsFlush(myHand))
                return PokerScore.Flush;
            else if (IsStraight(myHand))
                return PokerScore.Straight;
            else if (IsThreeOfAKind(myHand))
                return PokerScore.ThreeOfAKind;
            else if (IsTwoPair(myHand))
                return PokerScore.TwoPair;
            else if (IsJacksOrBetter(myHand))
                return PokerScore.JacksOrBetter;
            else
                return PokerScore.None;
        }

        public static int GetStatistics(Collection<Card> myCards, Collection<Card> tableCards)
        {
            if (myCards == null || tableCards == null)
            {
                return (0);
            }

            Card[] AuxiliarSortCard = new Card[myCards.Count + tableCards.Count];
            int ptrCard = 0;

            for (int ptr = 0; ptr < myCards.Count; ptr++)
            {
                AuxiliarSortCard[ptr] = myCards[ptr];
                ptrCard++;
            }

            for (int ptr = 0; ptr < tableCards.Count; ptr++)
            {
                AuxiliarSortCard[ptrCard] = tableCards[ptr];
                ptrCard++;
            }

            Array.Sort(AuxiliarSortCard);

            Collection<Card> Cards = new Collection<Card>();
            Collection<Card> Test = new Collection<Card>();
            for (int ptr = 0; ptr < AuxiliarSortCard.Length; ptr++)
            {
                Cards.Add(AuxiliarSortCard[ptr]);
            }


            int ReturnValueStat = 0;

            if (Cards.Count >= 5)
            {
                Test.Clear();
                for (int ptr = 0; ptr < 5; ptr++)
                {
                    Test.Add(Cards[ptr]);
                }
                PokerScore Value = ScoreCalculator(Test);
                ReturnValueStat = ReturnValueStat + (int)Value + 1;
            }

            if (Cards.Count >= 6)
            {
                Test.Clear();
                for (int ptr = 1; ptr < 6; ptr++)
                {
                    Test.Add(Cards[ptr]);
                }
                PokerScore Value = ScoreCalculator(Test);                                
                ReturnValueStat = ReturnValueStat + (int)Value + 1;
                
            }

            if (Cards.Count >= 7)
            {
                Test.Clear();
                for (int ptr = 2; ptr < 7; ptr++)
                {
                    Test.Add(Cards[ptr]);
                }
                PokerScore Value = ScoreCalculator(Test);
                ReturnValueStat = ReturnValueStat + (int)Value + 1;
            }


            ReturnValueStat = ReturnValueStat * 10;
            if (ReturnValueStat >= 100)
            {
                ReturnValueStat = 100;
            }
            return (ReturnValueStat);
        }

        public static Card ToCard(string suit, string rank)
        {
            if (String.IsNullOrEmpty(suit) || String.IsNullOrEmpty(rank))
            {
                return (null);
            }

            EnumRank RankAuxiliar;
            EnumSuit SuitAuxiliar;

            switch (suit)
            {
                case "Diamond":
                    SuitAuxiliar = EnumSuit.Diamond;
                    break;

                case "Heart":
                    SuitAuxiliar = EnumSuit.Heart;
                    break;

                case "Club":
                    SuitAuxiliar = EnumSuit.Club;
                    break;

                case "Spade":
                    SuitAuxiliar = EnumSuit.Spade;
                    break;

                default:
                    SuitAuxiliar = EnumSuit.None;
                    break;
            }

            switch (rank)
            {
                case "Ace":
                    RankAuxiliar = EnumRank.Ace;
                    break;

                case "Two":
                    RankAuxiliar = EnumRank.Two;
                    break;

                case "Three":
                    RankAuxiliar = EnumRank.Three;
                    break;

                case "Four":
                    RankAuxiliar = EnumRank.Four;
                    break;

                case "Five":
                    RankAuxiliar = EnumRank.Five;
                    break;

                case "Six":
                    RankAuxiliar = EnumRank.Six;
                    break;

                case "Seven":
                    RankAuxiliar = EnumRank.Seven;
                    break;

                case "Eigth":
                    RankAuxiliar = EnumRank.Eight;
                    break;

                case "Nine":
                    RankAuxiliar = EnumRank.Nine;
                    break;

                case "Ten":
                    RankAuxiliar = EnumRank.Ten;
                    break;

                case "Jack":
                    RankAuxiliar = EnumRank.Jack;
                    break;

                case "Queen":
                    RankAuxiliar = EnumRank.Queen;
                    break;

                case "King":
                    RankAuxiliar = EnumRank.King;
                    break;

                default:
                    RankAuxiliar = EnumRank.None;
                    break;
            }

            Card ReturnCardTransform = new Card(RankAuxiliar, SuitAuxiliar);
            return (ReturnCardTransform);
        }
    }
}
